<script setup>
import { getStore, setStore, getStoreByChunks, setStoreByChunks } from '../services/book-store'
import { getBookSourceRule, getChapterContent, getBookDetails, getBookChapters, saveBook, getDownloadSettings } from '../services/bookService'
import pLimit from 'p-limit';
import { useRoute } from 'vue-router';
import { ref, onMounted, onActivated, getCurrentInstance } from 'vue';
let limit;
const { proxy } = getCurrentInstance();
const route = useRoute();
// 下载列表
const downloadList = ref([]);


const mapDownloadList = () => {
  return downloadList.value.map(item=>{
    let data = {...item}
    delete data.state;
    delete data.stateText;
    delete data.progress;
    delete data.loading;
    return data;
  })
};

// 删除下载项
const removeDownload = (index) => {
  downloadList.value.splice(index, 1);
  setStore('downloadList', mapDownloadList());
};

// 打开文件
const openFile = (item) => {
  if (item.progress === 100) {
    window.utools && window.utools.shellShowItemInFolder(item.savePath);
  }
};


// 获取下载列表
const getDownloadList = () => {
  let downloadListStore = getStore('downloadList') || [];
  downloadList.value = downloadListStore.map(item=>{
    let toc = getStoreByChunks(`${item._id}_toc`) || [];
    let progress = getCacheProgress(toc);
    return {
      ...item,
     progress: progress || 0,
     state: false,
     stateText: progress === 100 ? '已完成' : '已暂停'
    }
  });
};

// 获取 缓存进度
const getCacheProgress = (param) => {
  let toc
  if(Array.isArray(param)){
    toc = param
  }else{
    toc = getStoreByChunks(`${param._id}_toc`) || [];
  }
  let total = toc.length, caches = toc.filter(item=>item.cache).length;
  let progress = total ? (caches / total) * 100 : 0;
  if(progress % 1 !== 0){
    return progress.toFixed(2);
  }else{
    return progress;
  }
}

const delay = (time) => {
  let config
  if(!time){
    config = getDownloadSettings()
  }
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve();
    }, time || config.riskControl.requestInterval);
  });
}

// 开始/继续 并发
const startDownloadList = async (book) => {
  book.state = true;
  book.loading = true;
  book.stateText = '正在下载';
  proxy.$toast.info('正在下载');
  const downloadSetting = getDownloadSettings();
  
  limit = pLimit(downloadSetting.maxConcurrent || 1);
  let bookSourceRule = getBookSourceRule(book);
  let toc = getStoreByChunks(`${book._id}_toc`) || [];
  let bookCacheData = getStoreByChunks(`${book._id}_content`) || [];
  if(!toc.length){
    try {
      let detail = await getBookDetails(book, bookSourceRule);
      toc = await getBookChapters(detail);
    } catch (error) {
      book.stateText = '已暂停';
      book.state = false;
      book.loading = false;
      proxy.$toast.error('资源出错无法下载');
      return;
    }
  }

  let tasks = toc.map(element=>{
    return limit(async()=>{
      if(!book.state)throw new Error('已暂停');
      if(element.cache)return;
      for (let i = 0; i < downloadSetting.retryCount + 1; i++) {
        await delay(downloadSetting.riskControl.requestInterval);
        if(i > 0){ console.log('第'+(i)+'次重试'); }
        try {
          const content = await getChapterContent(element.url, bookSourceRule)
          element.cache = true;
          bookCacheData[element.id] = {
            id: element.id,
            ...content
          }
          break;
        } catch (error) {
          console.log(error);
        }
      }
      book.progress = getCacheProgress(toc);
    })
  })
  
  let res = await Promise.allSettled(tasks)
  let progress = getCacheProgress(toc);
  if(progress < 100){
    book.stateText = '正在缓存下载数据';
    setStoreByChunks(`${book._id}_toc`, toc);
    setStoreByChunks(`${book._id}_content`, bookCacheData);
    book.stateText = '已暂停';
    book.state = false;
    book.loading = false;
    proxy.$toast.info('已暂停');
    return;
  }else{
    book.stateText = '正在缓存下载数据';
    book.progress = 100;
    setStoreByChunks(`${book._id}_toc`, toc);
    setStoreByChunks(`${book._id}_content`, bookCacheData);
    book.stateText = '正在保存文件';
    let path = await saveBook(bookCacheData, book);
    book.path = path;
    book.stateText = '已完成';
    proxy.$toast.success('已完成');
    book.state = false;
    book.loading = false;
    book.savePath = path;
    setStore('downloadList', mapDownloadList());
  }

}

// 开始/继续
const startDownload = async (book) => {
  book.state = true;
  book.stateText = '正在下载';
  let bookSourceRule = getBookSourceRule(book);
  let toc = getStoreByChunks(`${book._id}_toc`) || [];
  let bookCacheData = getStoreByChunks(`${book._id}_content`) || [];
  if(!toc.length){
    let detail = await getBookDetails(book, bookSourceRule);
    toc = await getBookChapters(detail);
  }
  for (let index = 0; index < toc.length; index++) {
    const element = toc[index];
    const downloadSetting = getDownloadSettings();
    if(element.cache){
      continue;
    }
    let retry = downloadSetting.retryCount;
    for (let i = 0; i < retry + 1; i++) {
      await delay(downloadSetting.riskControl.requestInterval);
      if(i > 0){ console.log('第'+(i)+'次重试'); }
      try {
        const content = await getChapterContent(element.url, bookSourceRule)
        element.cache = true;
        bookCacheData[index] = {
          id: index,
          ...content
        }
        break;
      }catch (error) {
        console.log(error);
      }
      
    }
    
    book.progress = getCacheProgress(toc);
    if(!book.state){
      book.stateText = '正在缓存下载数据';
      setStoreByChunks(`${book._id}_toc`, toc);
      setStoreByChunks(`${book._id}_content`, bookCacheData);
      book.stateText = '已暂停';
      break;
    }
  }
  let progress = getCacheProgress(toc);

  if(progress < 100){
    book.stateText = '正在缓存下载数据';
    setStoreByChunks(`${book._id}_toc`, toc);
    setStoreByChunks(`${book._id}_content`, bookCacheData);
    book.stateText = '已暂停';
    book.state = false;
    return;
  }else{
    book.stateText = '正在缓存下载数据';
    book.progress = 100;
    setStoreByChunks(`${book._id}_toc`, toc);
    setStoreByChunks(`${book._id}_content`, bookCacheData);
    book.stateText = '正在保存文件';
    let path = await saveBook(bookCacheData, book);
    book.path = path;
    book.stateText = '已完成';
    book.state = false;
    book.savePath = path;
    setStore('downloadList', mapDownloadList());
  }
 
}

// 暂停
const pauseDownload = (book) => {
  book.state = false;
  book.stateText = '准备暂停';
}


onMounted(() => {
  getDownloadList();
  
});

onActivated(()=>{
  if(route.query.id){
    let bookshelf = getStore('bookshelf') || [];
    let book = bookshelf.find(item=>item._id === route.query.id);
    if(book){
      let progress = getCacheProgress(book)
      
      downloadList.value.unshift({
        ...book,
        progress: progress,
        state: false
      })
      let b = downloadList.value.find(item=>item._id === book._id);
      // startDownload(b);
      startDownloadList(b);
      setStore('downloadList', mapDownloadList());
    }

  }
}) 

</script>

<template>
  <div class="download-page">
    <div v-if="downloadList.length === 0" class="empty-list">
      <p>暂无下载内容</p>
    </div>
    
    <div v-else class="download-list">
      <div 
        v-for="(item, index) in downloadList" 
        :key="item.id"
        class="download-item"
      >
        <div class="item-info" @click="openFile(item)">
          <div class="item-title">{{ item.title }}({{ item.sourceName }})</div>
          <div class="item-author">{{ item.author }}</div>
          <div class="item-meta">
            {{ item.stateText }}
          </div>
        </div>
        
        <div class="item-progress">
          <div class="progress-bar">
            <div 
              class="progress-filled" 
              :style="{ width: `${item.progress}%` }"
              :class="{ 'completed': item.progress === 100 }"
            ></div>
          </div>
          <div class="progress-text">{{ item.progress }}%</div>
        </div>
        
        <div class="item-actions">
          <button 
            v-if="!item.state && item.progress < 100" 
            class="action-btn download-btn"
            :disabled="item.loading"
            @click="startDownloadList(item)"
          >
            继续
          </button>
          <button 
            v-else-if="item.state && item.progress < 100" 
            class="action-btn pause-btn"
            @click="pauseDownload(item)"
          >
            暂停
          </button>
          <button 
            v-else 
            class="action-btn open-btn"
            @click="openFile(item)"
          >
            打开
          </button>
          <button 
            class="action-btn delete-btn"
            @click="removeDownload(index)"
          >
            删除
          </button>
        </div>
      </div>
    </div>
  </div>
</template>

<style scoped>
.download-page {
  padding: 16px;
}

h1 {
  font-size: 24px;
  margin-bottom: 20px;
  color: #333;
}

@media (prefers-color-scheme: dark) {
  h1 {
    color: #ecf0f1;
  }
}

.empty-list {
  text-align: center;
  padding: 40px 0;
  color: #999;
}

@media (prefers-color-scheme: dark) {
  .empty-list {
    color: #b2bec3;
  }
}

.download-list {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.download-item {
  background-color: #fff;
  border-radius: 8px;
  padding: 16px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
}

@media (prefers-color-scheme: dark) {
  .download-item {
    background-color: #2c3e50;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
  }
}

.item-info {
  cursor: pointer;
}

.item-title {
  font-size: 18px;
  font-weight: bold;
  margin-bottom: 4px;
  color: #333;
}

@media (prefers-color-scheme: dark) {
  .item-title {
    color: #ecf0f1;
  }
}

.item-author {
  font-size: 14px;
  color: #666;
  margin-bottom: 8px;
}

@media (prefers-color-scheme: dark) {
  .item-author {
    color: #b2bec3;
  }
}

.item-meta {
  text-align: right;
  font-size: 12px;
  height: 15px;
  color: #999;
  margin-bottom: 2px;
}

@media (prefers-color-scheme: dark) {
  .item-meta {
    color: #b2bec3;
  }
}

.item-progress {
  margin-bottom: 12px;
}

.progress-bar {
  height: 8px;
  background-color: #eee;
  border-radius: 4px;
  overflow: hidden;
  margin-bottom: 4px;
}

@media (prefers-color-scheme: dark) {
  .progress-bar {
    background-color: #34495e;
  }
}

.progress-filled {
  height: 100%;
  background-color: var(--blue);
  border-radius: 4px;
}

.progress-filled.completed {
  background-color: #4CAF50;
}

.progress-text {
  text-align: right;
  font-size: 12px;
  color: #666;
}

@media (prefers-color-scheme: dark) {
  .progress-text {
    color: #b2bec3;
  }
}

.item-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
}

.action-btn {
  padding: 3px 12px;
  border-radius: 4px;
  font-size: 12px;
}

.download-btn {
  background-color: var(--blue);
}

.open-btn {
  background-color: #4CAF50;
}

.delete-btn {
  background-color: #f44336;
}
</style>